//! 技术分析信号模块
//! 
//! 使用 ta-lib 构建的信号函数
//! tas = ta-lib signals 的缩写

use std::collections::HashMap;
use chrono::{DateTime, Utc};

use crate::objects::{NewBar as Bar, Direction, Freq};
use crate::objects::signal::SimpleSignal;
use crate::utils::ta::TaUtils;

/// 更新均线缓存
pub fn update_ma_cache(bars: &[Bar], ma_type: &str, timeperiod: usize) -> Vec<f64> {
    let closes: Vec<f64> = bars.iter().map(|bar| bar.close).collect();
    let ta_utils = TaUtils::new(crate::utils::ta::TaConfig {
        ma_periods: vec![timeperiod],
        macd_fast: 12,
        macd_slow: 26,
        macd_signal: 9,
        rsi_period: 14,
        bb_period: 20,
        bb_std: 2.0,
    });
    
    match ma_type.to_uppercase().as_str() {
        "SMA" => ta_utils.sma(&closes, timeperiod),
        "EMA" => ta_utils.ema(&closes, timeperiod),
        _ => ta_utils.sma(&closes, timeperiod), // 默认使用SMA
    }
}

/// 更新MACD缓存
pub fn update_macd_cache(
    bars: &[Bar],
    fastperiod: usize,
    slowperiod: usize,
    signalperiod: usize,
) -> (Vec<f64>, Vec<f64>, Vec<f64>) {
    let closes: Vec<f64> = bars.iter().map(|bar| bar.close).collect();
    let ta_utils = TaUtils::new(crate::utils::ta::TaConfig {
        ma_periods: vec![fastperiod],
        macd_fast: fastperiod,
        macd_slow: slowperiod,
        macd_signal: signalperiod,
        rsi_period: 14,
        bb_period: 20,
        bb_std: 2.0,
    });
    ta_utils.macd(&closes)
}

/// 更新布林带缓存
pub fn update_boll_cache(bars: &[Bar], timeperiod: usize, nbdev: f64) -> (Vec<f64>, Vec<f64>, Vec<f64>) {
    let closes: Vec<f64> = bars.iter().map(|bar| bar.close).collect();
    let ta_utils = TaUtils::new(crate::utils::ta::TaConfig {
        ma_periods: vec![timeperiod],
        macd_fast: 12,
        macd_slow: 26,
        macd_signal: 9,
        rsi_period: 14,
        bb_period: timeperiod,
        bb_std: nbdev,
    });
    ta_utils.bollinger_bands(&closes)
}

/// 更新KDJ缓存
pub fn update_kdj_cache(bars: &[Bar], fastk_period: usize, slowk_period: usize, slowd_period: usize) -> (Vec<f64>, Vec<f64>, Vec<f64>) {
    let highs: Vec<f64> = bars.iter().map(|bar| bar.high).collect();
    let lows: Vec<f64> = bars.iter().map(|bar| bar.low).collect();
    let closes: Vec<f64> = bars.iter().map(|bar| bar.close).collect();
    let ta_utils = TaUtils::new(crate::utils::ta::TaConfig {
        ma_periods: vec![fastk_period],
        macd_fast: 12,
        macd_slow: 26,
        macd_signal: 9,
        rsi_period: 14,
        bb_period: 20,
        bb_std: 2.0,
    });
    let (k, d) = ta_utils.stochastic(&highs, &lows, &closes, fastk_period);
    // 计算J值：J = 3*K - 2*D
    let j: Vec<f64> = k.iter().zip(d.iter())
        .map(|(k_val, d_val)| 3.0 * k_val - 2.0 * d_val)
        .collect();
    (k, d, j)
}

/// 更新RSI缓存
pub fn update_rsi_cache(bars: &[Bar], timeperiod: usize) -> Vec<f64> {
    let closes: Vec<f64> = bars.iter().map(|bar| bar.close).collect();
    let ta_utils = TaUtils::new(crate::utils::ta::TaConfig {
        ma_periods: vec![timeperiod],
        macd_fast: 12,
        macd_slow: 26,
        macd_signal: 9,
        rsi_period: timeperiod,
        bb_period: 20,
        bb_std: 2.0,
    });
    ta_utils.rsi(&closes)
}

/// 更新CCI缓存
pub fn update_cci_cache(bars: &[Bar], timeperiod: usize) -> Vec<f64> {
    let highs: Vec<f64> = bars.iter().map(|bar| bar.high).collect();
    let lows: Vec<f64> = bars.iter().map(|bar| bar.low).collect();
    let closes: Vec<f64> = bars.iter().map(|bar| bar.close).collect();
    let ta_utils = TaUtils::new(crate::utils::ta::TaConfig {
        ma_periods: vec![timeperiod],
        macd_fast: 12,
        macd_slow: 26,
        macd_signal: 9,
        rsi_period: 14,
        bb_period: 20,
        bb_std: 2.0,
    });
    ta_utils.cci(&highs, &lows, &closes, timeperiod)
}

/// 更新ATR缓存
pub fn update_atr_cache(bars: &[Bar], timeperiod: usize) -> Vec<f64> {
    let highs: Vec<f64> = bars.iter().map(|bar| bar.high).collect();
    let lows: Vec<f64> = bars.iter().map(|bar| bar.low).collect();
    let closes: Vec<f64> = bars.iter().map(|bar| bar.close).collect();
    let ta_utils = TaUtils::new(crate::utils::ta::TaConfig {
        ma_periods: vec![timeperiod],
        macd_fast: 12,
        macd_slow: 26,
        macd_signal: 9,
        rsi_period: 14,
        bb_period: 20,
        bb_std: 2.0,
    });
    ta_utils.atr(&highs, &lows, &closes, timeperiod)
}

/// 更新SAR缓存
pub fn update_sar_cache(bars: &[Bar], acceleration: f64, maximum: f64) -> Vec<f64> {
    let highs: Vec<f64> = bars.iter().map(|bar| bar.high).collect();
    let lows: Vec<f64> = bars.iter().map(|bar| bar.low).collect();
    // 注意：TaUtils中没有sar方法，这里暂时返回空向量
    vec![]
}

/// MACD基础信号
pub fn tas_macd_base_v221028(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let fastperiod = kwargs.get("fastperiod").unwrap_or(&12.0).to_owned() as usize;
    let slowperiod = kwargs.get("slowperiod").unwrap_or(&26.0).to_owned() as usize;
    let signalperiod = kwargs.get("signalperiod").unwrap_or(&9.0).to_owned() as usize;
    
    let (dif, dea, macd_values) = update_macd_cache(bars, fastperiod, slowperiod, signalperiod);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_dif = dif[dif.len() - 1];
    let current_dea = dea[dea.len() - 1];
    let current_macd = macd_values[macd_values.len() - 1];
    
    let prev_dif = dif[dif.len() - 2];
    let prev_dea = dea[dea.len() - 2];
    let prev_macd = macd_values[macd_values.len() - 2];
    
    // DIF金叉DEA
    let dif_cross_dea_up = prev_dif <= prev_dea && current_dif > current_dea;
    // DIF死叉DEA
    let dif_cross_dea_down = prev_dif >= prev_dea && current_dif < current_dea;
    
    // MACD金叉零轴
    let macd_cross_zero_up = prev_macd <= 0.0 && current_macd > 0.0;
    // MACD死叉零轴
    let macd_cross_zero_down = prev_macd >= 0.0 && current_macd < 0.0;
    
    signals.insert(
        "DIF金叉DEA".to_string(),
        SimpleSignal::new(
            "DIF金叉DEA".to_string(),
            dif_cross_dea_up,
            if dif_cross_dea_up { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "DIF死叉DEA".to_string(),
        SimpleSignal::new(
            "DIF死叉DEA".to_string(),
            dif_cross_dea_down,
            if dif_cross_dea_down { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "MACD金叉零轴".to_string(),
        SimpleSignal::new(
            "MACD金叉零轴".to_string(),
            macd_cross_zero_up,
            if macd_cross_zero_up { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "MACD死叉零轴".to_string(),
        SimpleSignal::new(
            "MACD死叉零轴".to_string(),
            macd_cross_zero_down,
            if macd_cross_zero_down { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// 均线基础信号
pub fn tas_ma_base_v221101(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let ma_type = kwargs.get("ma_type").map(|v| v.to_string()).unwrap_or("SMA".to_string());
    let timeperiod = kwargs.get("timeperiod").unwrap_or(&20.0).to_owned() as usize;
    
    let ma_values = update_ma_cache(bars, &ma_type, timeperiod);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_close = bars.last().unwrap().close;
    let current_ma = ma_values[ma_values.len() - 1];
    let prev_close = bars[bars.len() - 2].close;
    let prev_ma = ma_values[ma_values.len() - 2];
    
    // 价格上穿均线
    let price_cross_ma_up = prev_close <= prev_ma && current_close > current_ma;
    // 价格下穿均线
    let price_cross_ma_down = prev_close >= prev_ma && current_close < current_ma;
    
    // 均线向上
    let ma_up = current_ma > prev_ma;
    // 均线向下
    let ma_down = current_ma < prev_ma;
    
    signals.insert(
        "价格上穿均线".to_string(),
        SimpleSignal::new(
            "价格上穿均线".to_string(),
            price_cross_ma_up,
            if price_cross_ma_up { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "价格下穿均线".to_string(),
        SimpleSignal::new(
            "价格下穿均线".to_string(),
            price_cross_ma_down,
            if price_cross_ma_down { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "均线向上".to_string(),
        SimpleSignal::new(
            "均线向上".to_string(),
            ma_up,
            if ma_up { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "均线向下".to_string(),
        SimpleSignal::new(
            "均线向下".to_string(),
            ma_down,
            if ma_down { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// 布林带基础信号
pub fn tas_boll_vt_v230212(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let timeperiod = kwargs.get("timeperiod").unwrap_or(&20.0).to_owned() as usize;
    let nbdev = kwargs.get("nbdev").unwrap_or(&2.0).to_owned();
    
    let (upper, middle, lower) = update_boll_cache(bars, timeperiod, nbdev);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_close = bars.last().unwrap().close;
    let current_upper = upper[upper.len() - 1];
    let current_lower = lower[lower.len() - 1];
    let prev_close = bars[bars.len() - 2].close;
    let prev_upper = upper[upper.len() - 2];
    let prev_lower = lower[lower.len() - 2];
    
    // 价格突破上轨
    let price_break_upper = prev_close <= prev_upper && current_close > current_upper;
    // 价格跌破下轨
    let price_break_lower = prev_close >= prev_lower && current_close < current_lower;
    
    // 价格回到通道内
    let price_in_channel = current_close <= current_upper && current_close >= current_lower;
    
    signals.insert(
        "价格突破上轨".to_string(),
        SimpleSignal::new(
            "价格突破上轨".to_string(),
            price_break_upper,
            if price_break_upper { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "价格跌破下轨".to_string(),
        SimpleSignal::new(
            "价格跌破下轨".to_string(),
            price_break_lower,
            if price_break_lower { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "价格在通道内".to_string(),
        SimpleSignal::new(
            "价格在通道内".to_string(),
            price_in_channel,
            if price_in_channel { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// RSI基础信号
pub fn tas_rsi_base_v230227(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let timeperiod = kwargs.get("timeperiod").unwrap_or(&14.0).to_owned() as usize;
    let overbought = kwargs.get("overbought").unwrap_or(&70.0).to_owned();
    let oversold = kwargs.get("oversold").unwrap_or(&30.0).to_owned();
    
    let rsi_values = update_rsi_cache(bars, timeperiod);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_rsi = rsi_values[rsi_values.len() - 1];
    let prev_rsi = rsi_values[rsi_values.len() - 2];
    
    // RSI超买
    let rsi_overbought = current_rsi > overbought;
    // RSI超卖
    let rsi_oversold = current_rsi < oversold;
    
    // RSI金叉50
    let rsi_cross_50_up = prev_rsi <= 50.0 && current_rsi > 50.0;
    // RSI死叉50
    let rsi_cross_50_down = prev_rsi >= 50.0 && current_rsi < 50.0;
    
    signals.insert(
        "RSI超买".to_string(),
        SimpleSignal::new(
            "RSI超买".to_string(),
            rsi_overbought,
            if rsi_overbought { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "RSI超卖".to_string(),
        SimpleSignal::new(
            "RSI超卖".to_string(),
            rsi_oversold,
            if rsi_oversold { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "RSI金叉50".to_string(),
        SimpleSignal::new(
            "RSI金叉50".to_string(),
            rsi_cross_50_up,
            if rsi_cross_50_up { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "RSI死叉50".to_string(),
        SimpleSignal::new(
            "RSI死叉50".to_string(),
            rsi_cross_50_down,
            if rsi_cross_50_down { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// KDJ基础信号
pub fn tas_kdj_base_v221101(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let fastk_period = kwargs.get("fastk_period").unwrap_or(&9.0).to_owned() as usize;
    let slowk_period = kwargs.get("slowk_period").unwrap_or(&3.0).to_owned() as usize;
    let slowd_period = kwargs.get("slowd_period").unwrap_or(&3.0).to_owned() as usize;
    
    let (k_values, d_values, j_values) = update_kdj_cache(bars, fastk_period, slowk_period, slowd_period);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_k = k_values[k_values.len() - 1];
    let current_d = d_values[d_values.len() - 1];
    let current_j = j_values[j_values.len() - 1];
    
    let prev_k = k_values[k_values.len() - 2];
    let prev_d = d_values[d_values.len() - 2];
    
    // K金叉D
    let k_cross_d_up = prev_k <= prev_d && current_k > current_d;
    // K死叉D
    let k_cross_d_down = prev_k >= prev_d && current_k < current_d;
    
    // KDJ超买
    let kdj_overbought = current_k > 80.0 && current_d > 80.0;
    // KDJ超卖
    let kdj_oversold = current_k < 20.0 && current_d < 20.0;
    
    signals.insert(
        "K金叉D".to_string(),
        SimpleSignal::new(
            "K金叉D".to_string(),
            k_cross_d_up,
            if k_cross_d_up { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "K死叉D".to_string(),
        SimpleSignal::new(
            "K死叉D".to_string(),
            k_cross_d_down,
            if k_cross_d_down { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "KDJ超买".to_string(),
        SimpleSignal::new(
            "KDJ超买".to_string(),
            kdj_overbought,
            if kdj_overbought { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "KDJ超卖".to_string(),
        SimpleSignal::new(
            "KDJ超卖".to_string(),
            kdj_oversold,
            if kdj_oversold { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// CCI基础信号
pub fn tas_cci_base_v230402(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let timeperiod = kwargs.get("timeperiod").unwrap_or(&14.0).to_owned() as usize;
    let overbought = kwargs.get("overbought").unwrap_or(&100.0).to_owned();
    let oversold = kwargs.get("oversold").unwrap_or(&-100.0).to_owned();
    
    let cci_values = update_cci_cache(bars, timeperiod);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_cci = cci_values[cci_values.len() - 1];
    let prev_cci = cci_values[cci_values.len() - 2];
    
    // CCI超买
    let cci_overbought = current_cci > overbought;
    // CCI超卖
    let cci_oversold = current_cci < oversold;
    
    // CCI金叉零轴
    let cci_cross_zero_up = prev_cci <= 0.0 && current_cci > 0.0;
    // CCI死叉零轴
    let cci_cross_zero_down = prev_cci >= 0.0 && current_cci < 0.0;
    
    signals.insert(
        "CCI超买".to_string(),
        SimpleSignal::new(
            "CCI超买".to_string(),
            cci_overbought,
            if cci_overbought { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "CCI超卖".to_string(),
        SimpleSignal::new(
            "CCI超卖".to_string(),
            cci_oversold,
            if cci_oversold { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "CCI金叉零轴".to_string(),
        SimpleSignal::new(
            "CCI金叉零轴".to_string(),
            cci_cross_zero_up,
            if cci_cross_zero_up { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "CCI死叉零轴".to_string(),
        SimpleSignal::new(
            "CCI死叉零轴".to_string(),
            cci_cross_zero_down,
            if cci_cross_zero_down { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// ATR突破信号
pub fn tas_atr_break_v230424(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let timeperiod = kwargs.get("timeperiod").unwrap_or(&14.0).to_owned() as usize;
    let multiplier = kwargs.get("multiplier").unwrap_or(&2.0).to_owned();
    
    let atr_values = update_atr_cache(bars, timeperiod);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_atr = atr_values[atr_values.len() - 1];
    let current_close = bars.last().unwrap().close;
    let current_high = bars.last().unwrap().high;
    let current_low = bars.last().unwrap().low;
    
    let upper_band = current_close + multiplier * current_atr;
    let lower_band = current_close - multiplier * current_atr;
    
    // 价格突破上轨
    let price_break_upper = current_high > upper_band;
    // 价格跌破下轨
    let price_break_lower = current_low < lower_band;
    
    signals.insert(
        "ATR突破上轨".to_string(),
        SimpleSignal::new(
            "ATR突破上轨".to_string(),
            price_break_upper,
            if price_break_upper { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "ATR跌破下轨".to_string(),
        SimpleSignal::new(
            "ATR跌破下轨".to_string(),
            price_break_lower,
            if price_break_lower { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// SAR基础信号
pub fn tas_sar_base_v230425(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let acceleration = kwargs.get("acceleration").unwrap_or(&0.02).to_owned();
    let maximum = kwargs.get("maximum").unwrap_or(&0.2).to_owned();
    
    let sar_values = update_sar_cache(bars, acceleration, maximum);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_close = bars.last().unwrap().close;
    let current_sar = sar_values[sar_values.len() - 1];
    let prev_close = bars[bars.len() - 2].close;
    let prev_sar = sar_values[sar_values.len() - 2];
    
    // 价格上穿SAR
    let price_cross_sar_up = prev_close <= prev_sar && current_close > current_sar;
    // 价格下穿SAR
    let price_cross_sar_down = prev_close >= prev_sar && current_close < current_sar;
    
    signals.insert(
        "价格上穿SAR".to_string(),
        SimpleSignal::new(
            "价格上穿SAR".to_string(),
            price_cross_sar_up,
            if price_cross_sar_up { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "价格下穿SAR".to_string(),
        SimpleSignal::new(
            "价格下穿SAR".to_string(),
            price_cross_sar_down,
            if price_cross_sar_down { Direction::Down } else { Direction::Up },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
} 

/// MACD方向信号
pub fn tas_macd_direct_v221106(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let fastperiod = kwargs.get("fastperiod").unwrap_or(&12.0).to_owned() as usize;
    let slowperiod = kwargs.get("slowperiod").unwrap_or(&26.0).to_owned() as usize;
    let signalperiod = kwargs.get("signalperiod").unwrap_or(&9.0).to_owned() as usize;
    
    let (dif, dea, macd_values) = update_macd_cache(bars, fastperiod, slowperiod, signalperiod);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 3 {
        return signals;
    }
    
    let current_macd = macd_values[macd_values.len() - 1];
    let prev_macd = macd_values[macd_values.len() - 2];
    let prev_prev_macd = macd_values[macd_values.len() - 3];
    
    // 连续三根MACD柱子值依次增大，向上；反之，向下
    let direction = if current_macd > prev_macd && prev_macd > prev_prev_macd {
        "向上"
    } else if current_macd < prev_macd && prev_macd < prev_prev_macd {
        "向下"
    } else {
        "模糊"
    };
    
    signals.insert(
        "MACD方向".to_string(),
        SimpleSignal::new(
            "MACD方向".to_string(),
            direction == "向上" || direction == "向下",
            if direction == "向上" { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// MACD强弱信号
pub fn tas_macd_power_v221108(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let fastperiod = kwargs.get("fastperiod").unwrap_or(&12.0).to_owned() as usize;
    let slowperiod = kwargs.get("slowperiod").unwrap_or(&26.0).to_owned() as usize;
    let signalperiod = kwargs.get("signalperiod").unwrap_or(&9.0).to_owned() as usize;
    
    let (dif, dea, _) = update_macd_cache(bars, fastperiod, slowperiod, signalperiod);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_dif = dif[dif.len() - 1];
    let current_dea = dea[dea.len() - 1];
    
    let strength = if current_dif >= current_dea && current_dea >= 0.0 {
        "超强"
    } else if current_dif - current_dea > 0.0 {
        "强势"
    } else if current_dif <= current_dea && current_dea <= 0.0 {
        "超弱"
    } else if current_dif - current_dea < 0.0 {
        "弱势"
    } else {
        "其他"
    };
    
    signals.insert(
        "MACD强弱".to_string(),
        SimpleSignal::new(
            "MACD强弱".to_string(),
            strength != "其他",
            if strength == "超强" || strength == "强势" { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// 双均线信号
pub fn tas_double_ma_v221203(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let ma_type = kwargs.get("ma_type").map(|v| v.to_string()).unwrap_or("SMA".to_string());
    let timeperiod1 = kwargs.get("timeperiod1").unwrap_or(&5.0).to_owned() as usize;
    let timeperiod2 = kwargs.get("timeperiod2").unwrap_or(&10.0).to_owned() as usize;
    let th = kwargs.get("th").unwrap_or(&100.0).to_owned();
    
    let ma1_values = update_ma_cache(bars, &ma_type, timeperiod1);
    let ma2_values = update_ma_cache(bars, &ma_type, timeperiod2);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_ma1 = ma1_values[ma1_values.len() - 1];
    let current_ma2 = ma2_values[ma2_values.len() - 1];
    
    // ma1 > ma2，多头；反之，空头
    let position = if current_ma1 >= current_ma2 { "多头" } else { "空头" };
    
    // ma1 离开 ma2 的距离大于 th，强势；反之，弱势
    let strength = if (current_ma1 - current_ma2).abs() / current_ma2 * 10000.0 >= th {
        "强势"
    } else {
        "弱势"
    };
    
    signals.insert(
        "双均线多空".to_string(),
        SimpleSignal::new(
            "双均线多空".to_string(),
            position == "多头",
            if position == "多头" { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "双均线强弱".to_string(),
        SimpleSignal::new(
            "双均线强弱".to_string(),
            strength == "强势",
            if strength == "强势" { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// 布林带强弱信号
pub fn tas_boll_power_v221112(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let timeperiod = kwargs.get("timeperiod").unwrap_or(&20.0).to_owned() as usize;
    
    let (upper, middle, lower) = update_boll_cache(bars, timeperiod, 2.0);
    
    let mut signals = HashMap::new();
    
    if bars.len() < 2 {
        return signals;
    }
    
    let current_close = bars.last().unwrap().close;
    let current_upper = upper[upper.len() - 1];
    let current_middle = middle[middle.len() - 1];
    let current_lower = lower[lower.len() - 1];
    
    // close大于中线，多头；反之，空头
    let position = if current_close >= current_middle { "多头" } else { "空头" };
    
    // close超过轨3，超强，以此类推
    let strength = if current_close >= current_upper {
        "极强"
    } else if current_close >= current_middle + (current_upper - current_middle) * 0.5 {
        "超强"
    } else if current_close >= current_middle {
        "强势"
    } else {
        "弱势"
    };
    
    signals.insert(
        "布林带多空".to_string(),
        SimpleSignal::new(
            "布林带多空".to_string(),
            position == "多头",
            if position == "多头" { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals.insert(
        "布林带强弱".to_string(),
        SimpleSignal::new(
            "布林带强弱".to_string(),
            strength == "极强" || strength == "超强" || strength == "强势",
            if strength == "极强" || strength == "超强" || strength == "强势" { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// KDJ极值计数信号
pub fn tas_kdj_evc_v221201(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let fastk_period = kwargs.get("fastk_period").unwrap_or(&9.0).to_owned() as usize;
    let slowk_period = kwargs.get("slowk_period").unwrap_or(&3.0).to_owned() as usize;
    let slowd_period = kwargs.get("slowd_period").unwrap_or(&3.0).to_owned() as usize;
    let th = kwargs.get("th").unwrap_or(&10.0).to_owned();
    let min_count = kwargs.get("min_count").unwrap_or(&5.0).to_owned() as usize;
    let max_count = kwargs.get("max_count").unwrap_or(&8.0).to_owned() as usize;
    
    let (k_values, d_values, j_values) = update_kdj_cache(bars, fastk_period, slowk_period, slowd_period);
    
    let mut signals = HashMap::new();
    
    if bars.len() < max_count + 3 {
        return signals;
    }
    
    // 计算连续K值小于th的次数
    let mut long_count = 0;
    let mut short_count = 0;
    
    for i in (k_values.len() - max_count)..k_values.len() {
        if k_values[i] < th {
            long_count += 1;
        } else {
            long_count = 0;
        }
        
        if k_values[i] > 100.0 - th {
            short_count += 1;
        } else {
            short_count = 0;
        }
    }
    
    let position = if max_count > long_count && long_count >= min_count {
        "多头"
    } else if max_count > short_count && short_count >= min_count {
        "空头"
    } else {
        "其他"
    };
    
    signals.insert(
        "KDJ极值".to_string(),
        SimpleSignal::new(
            "KDJ极值".to_string(),
            position != "其他",
            if position == "多头" { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// MACD变色次数信号
pub fn tas_macd_change_v221105(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let fastperiod = kwargs.get("fastperiod").unwrap_or(&12.0).to_owned() as usize;
    let slowperiod = kwargs.get("slowperiod").unwrap_or(&26.0).to_owned() as usize;
    let signalperiod = kwargs.get("signalperiod").unwrap_or(&9.0).to_owned() as usize;
    let n = kwargs.get("n").unwrap_or(&55.0).to_owned() as usize;
    
    let (dif, dea, _) = update_macd_cache(bars, fastperiod, slowperiod, signalperiod);
    
    let mut signals = HashMap::new();
    
    if bars.len() < n {
        return signals;
    }
    
    // 计算金叉死叉次数
    let mut cross_count = 0;
    for i in 1..dif.len() {
        if (dif[i] > dea[i] && dif[i-1] <= dea[i-1]) || (dif[i] < dea[i] && dif[i-1] >= dea[i-1]) {
            cross_count += 1;
        }
    }
    
    signals.insert(
        "MACD变色次数".to_string(),
        SimpleSignal::new(
            "MACD变色次数".to_string(),
            cross_count > 0,
            if cross_count > 0 { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// 均线系统多空排列信号
pub fn tas_ma_system_v230513(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let ma_seq = kwargs.get("ma_seq").map(|v| v.to_string()).unwrap_or("5#10#20".to_string());
    let ma_periods: Vec<usize> = ma_seq.split('#').map(|s| s.parse().unwrap_or(5)).collect();
    
    let mut signals = HashMap::new();
    
    if bars.len() < ma_periods.iter().max().unwrap() + 10 {
        return signals;
    }
    
    let mut ma_values = Vec::new();
    for period in &ma_periods {
        let values = update_ma_cache(bars, "SMA", *period);
        ma_values.push(values[values.len() - 1]);
    }
    
    // 检查是否多头排列：5日均线 > 10日均线 > 20日均线
    let mut is_long = true;
    for i in 0..ma_values.len()-1 {
        if ma_values[i] <= ma_values[i+1] {
            is_long = false;
            break;
        }
    }
    
    // 检查是否空头排列：5日均线 < 10日均线 < 20日均线
    let mut is_short = true;
    for i in 0..ma_values.len()-1 {
        if ma_values[i] >= ma_values[i+1] {
            is_short = false;
            break;
        }
    }
    
    let position = if is_long { "多头排列" } else if is_short { "空头排列" } else { "其他" };
    
    signals.insert(
        "均线系统".to_string(),
        SimpleSignal::new(
            "均线系统".to_string(),
            position != "其他",
            if position == "多头排列" { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
}

/// ATR波动强弱信号
pub fn tas_atr_v230630(bars: &[Bar], kwargs: &HashMap<String, f64>) -> HashMap<String, SimpleSignal> {
    let timeperiod = kwargs.get("timeperiod").unwrap_or(&14.0).to_owned() as usize;
    
    let atr_values = update_atr_cache(bars, timeperiod);
    
    let mut signals = HashMap::new();
    
    if bars.len() < timeperiod + 8 {
        return signals;
    }
    
    let current_atr = atr_values[atr_values.len() - 1];
    let current_close = bars.last().unwrap().close;
    let atr_ratio = current_atr / current_close;
    
    // 将ATR比率分成10层
    let layer = if atr_ratio < 0.01 { 1 } else if atr_ratio < 0.02 { 2 } else if atr_ratio < 0.03 { 3 }
                else if atr_ratio < 0.04 { 4 } else if atr_ratio < 0.05 { 5 } else if atr_ratio < 0.06 { 6 }
                else if atr_ratio < 0.07 { 7 } else if atr_ratio < 0.08 { 8 } else if atr_ratio < 0.09 { 9 } else { 10 };
    
    signals.insert(
        "ATR波动".to_string(),
        SimpleSignal::new(
            "ATR波动".to_string(),
            true,
            if layer >= 5 { Direction::Up } else { Direction::Down },
            bars.last().unwrap().dt,
        ),
    );
    
    signals
} 


 